package grow

import (
	"server/game/cache"
	"server/game/model"
	"server/share/config"
	"strings"

	"github.com/hwcer/cosgo/random"
	"github.com/hwcer/cosgo/registry"
	"github.com/hwcer/cosgo/slice"
	"github.com/hwcer/updater"
	"github.com/hwcer/updater/dataset"
	"github.com/hwcer/yyds"
	"github.com/hwcer/yyds/context"
	"github.com/hwcer/yyds/errors"
)

func init() {
	Register(&chip{})
}

// 芯片 装备
type chip struct {
}

func (this *chip) Caller(node *registry.Node, handle *context.Context) interface{} {
	f := node.Method().(func(*chip, *context.Context) interface{})
	return f(this, handle)
}

/**
 * @name levelUp
 * @param string key 芯片唯一ID
 * @param int lv 增加等级
 * 升级（强化）
 */
func (this *chip) LevelUp(c *context.Context) any {
	key := c.GetString("key")
	if key == "" {
		return errors.ErrArgEmpty
	}
	lv := c.GetInt32("lv")
	if lv == 0 {
		return errors.ErrArgEmpty
	}
	coll := cache.GetItems(c.Player.Updater)
	equip := coll.Get(key)
	if equip == nil {
		return errors.ErrDataNotExists
	}
	equipConfig := config.Data.Chip[equip.IID]
	if equipConfig == nil {
		return errors.ErrConfigEmpty
	}
	if equipConfig.ChipKind != 1 {
		return c.Error("芯片类型错误")
	}
	elv := equip.Attach.GetInt32(model.AttachChipLv) + lv
	tk := equipConfig.ChipKind*10000 + equipConfig.RareKey*1000 + elv
	if chipLv := config.Data.ChipLv[tk]; chipLv == nil {
		return c.Error("不能超过最大等级")
	}

	subs := map[int32]int32{}
	attr := map[int32]*model.ChipOtherAttr{}
	rand := random.New(nil)
	if err := equip.Attach.Unmarshal(model.AttachChipOtherAttr, &attr); err != nil {
		return err
	}

	for k, v := range attr {
		rand.Add(k, v.Weight)
	}

	var skillLvUp bool

	for i := equip.Attach.GetInt32(model.AttachChipLv); i < elv; i++ {
		tk = equipConfig.ChipKind*10000 + equipConfig.RareKey*1000 + i
		expConfig := config.Data.ChipLv[tk]
		if expConfig == nil {
			return c.Error("消耗配置不存在")
		}
		for _, sub := range expConfig.Sub {
			if sub.Id > 0 && sub.Num > 0 {
				subs[sub.Id] += sub.Num
			}
		}
		chipAdvance := config.Data.Base["chipAdvance"]
		if chipAdvance != nil && i%chipAdvance.Val == 0 {
			//attrNum := len(equip.OtherAttr)
			//todo 优先填满属性
			if k := rand.Roll(); k > 0 {
				skillLvUp = true
				a := attr[k]
				a.Lv++
				attr[k] = a
			}
		}
	}
	for k, v := range subs {
		c.Player.Sub(k, v)
	}
	up := dataset.Update{}
	up[model.AttachChipLv] = elv
	if skillLvUp {
		up[model.AttachChipOtherAttr] = attr
	}

	coll.SetAttachBatch(key, up)
	c.Player.Emit(config.Data.Events.ChipLevelUp, 1)
	return nil
}

/**
 * @name extraLevelUp
 * @param string key 芯片唯一ID
 * @param int id 芯片属性ID
 * 特殊芯片升级（强化）
 */
func (this *chip) ExtraLevelUp(c *context.Context) any {
	id := c.GetInt32("id")
	key := c.GetString("key")
	if key == "" {
		return errors.ErrArgEmpty
	}
	coll := cache.GetItems(c.Player.Updater)
	equip := coll.Get(key)
	if equip == nil {
		return errors.ErrDataNotExists
	}
	equipConfig := config.Data.Chip[equip.IID]
	if equipConfig == nil {
		return errors.ErrConfigEmpty
	}
	if equipConfig.ChipKind != 2 {
		return c.Error("芯片类型错误")
	}
	elv := equip.Attach.GetInt32(model.AttachChipLv) + 1
	sk := equipConfig.ChipKind*10000 + equipConfig.RareKey*1000 + elv
	if sConfig := config.Data.ChipLv[sk]; sConfig == nil {
		return c.Error("已经是最大强化等级")
	}

	extra := map[int32]*model.ChipExtraAttr{}
	if err := equip.Attach.Unmarshal(model.AttachChipExtraAttr, &extra); err != nil {
		return err
	}

	attr := extra[id]
	if attr == nil {
		return c.Error("本词条不存在")
	}
	if len(attr.Data) >= 10 {
		return c.Error("本词条已经强化完毕")
	}
	var baseRate int32
	var changeRate int32
	if baseRateConfig := config.Data.Base["beginSpchipAdvance"]; baseRateConfig != nil {
		baseRate = baseRateConfig.Val
	}
	if changeRateConfig := config.Data.Base["spchipAdvance"]; changeRateConfig != nil {
		changeRate = changeRateConfig.Val
	}
	for _, et := range extra {
		for _, v := range et.Data {
			if v > 0 {
				baseRate -= changeRate
			} else {
				baseRate += changeRate
			}
		}
	}
	if random.Probability(baseRate, 100) {
		attr.Data = append(attr.Data, 1)
	} else {
		attr.Data = append(attr.Data, 0)
	}
	sk = equipConfig.ChipKind*10000 + equipConfig.RareKey*1000 + equip.Attach.GetInt32(model.AttachChipLv)
	sc := config.Data.ChipLv[sk]
	if sc == nil {
		return errors.ErrConfigEmpty
	}
	c.Player.SubItems(sc.Sub)

	up := dataset.Update{}
	up[model.AttachChipLv] = elv
	up[model.AttachChipExtraAttr] = extra
	coll.SetAttachBatch(key, up)
	c.Player.Emit(config.Data.Events.ChipLevelUp, 1)

	return nil
}

/**
 * @name setChip
 * @param string unitKey 单位唯一ID
 * @param string chipKey 芯片唯一ID ,如果为空代表卸下对应芯片
 * @param int site 安装位置
 * 安装芯片
 */

func (this *chip) SetChip(c *context.Context) any {
	unitKey := c.GetString("unitKey")
	chipKey := c.GetString("chipKey")
	site := c.GetInt32("site")
	if unitKey == "" || site == 0 {
		return errors.ErrArgEmpty
	}
	chipPos := config.Data.ChipPos[site]
	if chipPos == nil {
		return errors.ErrConfigEmpty
	}

	items := cache.GetItems(c.Player.Updater)
	unitData := items.Get(unitKey)
	if unitData == nil {
		return errors.ErrDataNotExists
	}
	if _, ok := config.Data.Unit[unitData.IID]; !ok {
		return c.Error("只能给角色使用芯片")
	}
	equips := map[int32]string{}
	if err := unitData.Attach.Unmarshal(model.AttachUnitChipList, &equips); err != nil {
		return err
	}

	if chipKey != "" {
		chipData := items.Get(chipKey)
		if chipData == nil {
			return errors.ErrDataNotExists
		}
		if !yyds.Config.Is(chipData.IID, config.ITypeChip) {
			return c.Error("选择的物品不是芯片")
		}
		if exist := items.Equip.Get(chipKey); exist != "" {
			if exist == unitKey {
				return true
			} else {
				return c.Error("已经在其他单位上使用")
			}
		}
		chipConfig := config.Data.Chip[chipData.IID]
		if chipConfig == nil {
			return errors.ErrConfigEmpty
		}
		if chipPos.ChipKind != chipConfig.ChipKind {
			return c.Error("装备部位不对")
		}

		//equip := equips[site] //TODO 如果卸下另外一个以目前业务，需要额外通知客户端
		equips[site] = chipKey
		//c.Player.Updater.On(updater.EventTypeSuccess, func(u *updater.Updater) (next bool) {
		//	items.Equip.Use(chipKey, unitKey)
		//	if equip != "" {
		//		items.Equip.Del(equip)
		//	}
		//	return false
		//})
	} else {
		//卸载
		chipKey = equips[site]
		if chipKey == "" {
			return false
		}
		delete(equips, site)
	}
	items.SetAttach(unitKey, model.AttachUnitChipList, equips)
	return nil
}

/**
 * @name setAllChip
 * @param string unitKey 单位唯一ID
 * @param json chipList 安装内容
 * 一键安装芯片
 */

func (this *chip) SetAllChip(c *context.Context) any {
	args := struct {
		UnitKey  string           `json:"unitKey"`
		ChipList map[int32]string `json:"chipList"`
	}{
		ChipList: make(map[int32]string),
	}
	if err := c.Bind(&args); err != nil {
		return err
	}

	items := cache.GetItems(c.Player.Updater)
	unitData := items.Get(args.UnitKey)
	if unitData == nil {
		return errors.ErrDataNotExists
	}

	req := map[string]struct{}{}
	for _, v := range args.ChipList {
		if d := items.Get(v); d == nil {
			return errors.ErrDataNotExists
		} else if !yyds.Config.Is(d.IID, config.ITypeChip) {
			return c.Errorf(0, "选择的物品不是芯片:%s", v)
		}
		if _, ok := req[v]; ok {
			return c.Errorf(0, "不能重复装备:%s", v)
		}
		req[v] = struct{}{}
	}
	//查询使用情况
	used := items.Equip.MGet(req)
	for k, v := range used {
		if v != args.UnitKey {
			return c.Errorf(0, "已经在其他单位上使用:%s", k)
		}
	}

	items.SetAttach(args.UnitKey, model.AttachUnitChipList, args.ChipList)
	//c.Player.Updater.On(updater.EventTypeSuccess, func(u *updater.Updater) (next bool) {
	//	items.Equip.Del(cur...)
	//	for k, _ := range req {
	//		items.Equip.Use(k, args.UnitKey)
	//	}
	//	return false
	//})

	return nil
}

/**
 * @name unsetAllChip
 * @param string unitKey 单位唯一ID
 * 一键卸载芯片
 */

func (this *chip) UnsetAllChip(c *context.Context) any {
	unitKey := c.GetString("unitKey")
	if unitKey == "" {
		return errors.ErrArgEmpty
	}
	items := cache.GetItems(c.Player.Updater)
	unitData := items.Get(unitKey)
	if unitData == nil {
		return errors.ErrDataNotExists
	}
	equips := map[int32]string{}
	if err := unitData.Attach.Unmarshal(model.AttachUnitChipList, &equips); err != nil {
		return err
	}
	items.SetAttach(unitKey, model.AttachUnitChipList, make(map[string]string))
	c.Player.Updater.On(updater.EventTypeSuccess, func(u *updater.Updater) (next bool) {
		for _, k := range equips {
			items.Equip.Del(k)
		}
		return false
	})
	return nil
}

/**
 * @name refine
 * @param string sub 芯片ID串,以","分割
 * 分解,锁定，装备中的芯片无法分解
 */

func (this *chip) Refine(c *context.Context) any {
	sub := c.GetString("sub")
	if sub == "" {
		return errors.ErrArgEmpty
	}
	arr := strings.Split(sub, ",")
	arr = slice.Unrepeated(arr)
	if len(arr) == 0 {
		return errors.ErrArgEmpty
	}
	items := cache.GetItems(c.Player.Updater)

	success := make(map[string]bool)
	for _, v := range arr {
		data := items.Get(v)
		if data == nil {
			continue
		}
		if !yyds.Config.Is(data.IID, config.ITypeChip) {
			continue
		}
		if data.Attach.GetInt32(model.AttachTypeLocked) > 0 {
			continue
		}
		if items.Equip.Has(v) {
			continue
		}
		if success[v] {
			continue
		}
		chipConfig := config.Data.Chip[data.IID]
		if chipConfig == nil {
			continue
		}
		configId := chipConfig.ChipKind*10000 + chipConfig.RareKey*1000 + data.Attach.GetInt32(model.AttachChipLv)
		sConfig := config.Data.ChipLv[configId]
		if sConfig == nil {
			continue
		}
		success[v] = true
		items.Del(v)
		c.Player.AddItems(sConfig.Resolve)
	}
	return success
}
